package cxydmmszl.chapter08.t135;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * <li style="color: red;">Prob</li>
 * 边界都是 1 的最大正方形大小
 * <li style="color: red;">Desc</li>
 *
 * <li style="color: red;">Link</li> CD41
 *
 * @author habitplus
 * @since 2021-09-06 19:02
 */
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(bf.readLine());
//        int m = Integer.parseInt(ss[1]);
        int[][] arr = new int[n][n];

        String[] ss;
        for (int i = 0; i < n; i++) {
            ss = bf.readLine().split(" ");
            for (int j = 0; j < n; j++) {
                arr[i][j] = Integer.parseInt(ss[j]);
            }
        }
        bf.close();

        int ans = getMaxSize(arr);
        System.out.println(ans);
    }

    public static int getMaxSize(int[][] arr) {
        if (arr == null || arr.length == 0 || arr[0].length == 0) {
            return 0;
        }

        int n = arr.length;
        int m = arr[0].length;
        // 预处理阶段
        // right[i][j] 表示从 arr[i][j] 开始往右，有多少个连续的 1
        int[][] right = new int[n][m];
        // down[i][j] 表示从 arr[i][j] 开始往下，有多少个连续的 1
        int[][] down = new int[n][m];

        setBorderMap(arr, right, down);

        for (int sz = Math.min(m, n); sz > 0; sz--) {
            if (hasSizeOfBorder(sz, right, down)) {
                return sz;
            }
        }
        return 0;
    }

    private static boolean hasSizeOfBorder(int size, int[][] right, int[][] down) {

        for (int i = 0; i < right.length - size + 1; i++) {
            for (int j = 0; j < right[0].length - size + 1; j++) {
                if (right[i][j] >= size && down[i][j] >= size
                        && right[i + size - 1][j] >= size
                        && down[i][j + size - 1] >= size) {
                    return true;
                }
            }
        }
        return false;
    }

    private static void setBorderMap(int[][] arr, int[][] right, int[][] down) {
        int n = arr.length;
        int m = arr[0].length;

        right[n - 1][m - 1] = arr[n - 1][m - 1];
        down[n - 1][m - 1] = arr[n - 1][m - 1];

        for (int i = m - 2; i >= 0; i--) {
            if (arr[n - 1][i] == 1) {
                right[n - 1][i] = right[n - 1][i + 1] + 1;
                down[n - 1][i] = 1;
            }
        }

        for (int i = n - 2; i >= 0; i--) {
            if (arr[i][m - 1] == 1) {
                down[i][m - 1] = down[i + 1][m - 1] + 1;
                right[i][m - 1] = 1;
            }

        }

        for (int i = n - 2; i >= 0; i--) {
            for (int j = m - 2; j >= 0; j--) {
                if (arr[i][j] == 1) {
                    right[i][j] = right[i][j + 1] + 1;
                    down[i][j] = down[i + 1][j] + 1;
                }
            }
        }
    }
}
